
#include "openssl/err.h"
#include "openssl/bio.h"
#include "openssl/ssl.h"

#include "openssl/objects.h"
#include "openssl/rand.h"
#include "openssl/aes.h"
#include "openssl/rsa.h"
#include "openssl/md5.h"

#include <assert.h>


int main()
{
	unsigned char rand[1024];
	unsigned char raw[128];
	unsigned char out[128];
	int ret;

	RAND_bytes(rand, 1024);

	/* AES algorithm */
	memset(raw, 0, sizeof(raw));
	memset(out, 0, sizeof(out));

	for (int i=0; i<16; i++)
		raw[i] = '0' + i%8;

	AES_KEY aesKey;
	ret = AES_set_encrypt_key(rand, 256, &aesKey);
	assert(ret == 0);
	
	// only 16 bytes are encrypted
	AES_encrypt(raw, out, &aesKey);

	memset(raw, 0, 128);

	ret = AES_set_decrypt_key(rand, 256, &aesKey);
	assert(ret == 0);

	AES_decrypt(out, raw, &aesKey);

	/* RSA algorithm */
	memset(raw, 0, 128);
	memset(out, 0, 128);

	for (int i=0; i<117; i++)
		raw[i] = '0' + i%8;

	RSA *rsaKey = RSA_new();
	rsaKey = RSA_generate_key(1024, RSA_3, NULL, NULL);

	assert(RSA_size(rsaKey) == 128);
	assert(RSA_check_key(rsaKey) == 1);
	
	//reserve 11 bytes to contain padding
	int len = RSA_public_encrypt(117, raw, out, rsaKey, RSA_PKCS1_PADDING); 
	assert(len == 128);

	memset(raw, 0, 128);

	len = RSA_private_decrypt(len, out, raw, rsaKey, RSA_PKCS1_PADDING);
	assert(len == 117);

	unsigned char sigBuf[256];
	unsigned int sigLen = 256;

	ret = RSA_sign(NID_md5, (const unsigned char *)"atto", 4, sigBuf, &sigLen, rsaKey);
	assert(ret == 1);

	ret = RSA_verify(NID_md5, (const unsigned char *)"atto", 4, sigBuf, sigLen, rsaKey);
	assert(ret == 1);

	RSA_free(rsaKey);

	/* MD5 algorithm */
	memset(raw, 0, 128);

	for (int i=0; i<128; i++)
		raw[i] = '0' + i%8;

	MD5_CTX md5Ctx;
	unsigned char md[32];

	memset(md, 0, sizeof(md));

	ret = MD5_Init(&md5Ctx);
	assert(ret == 1);
	
	ret = MD5_Update(&md5Ctx, raw, 32); 
	assert(ret == 1);
	ret = MD5_Update(&md5Ctx, raw+32, 32); 
	assert(ret == 1);
	ret = MD5_Update(&md5Ctx, raw+64, 32); 
	assert(ret == 1);
	ret = MD5_Update(&md5Ctx, raw+96, 32); 
	assert(ret == 1);

	ret = MD5_Final(md, &md5Ctx); 
	assert(ret == 1);

	memset(md, 0, sizeof(md));
	MD5(raw, 128, md);

	return 0;
}

